package zlib

import (
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"net"
	"reflect"
	"strconv"
	"strings"
	"unicode/utf8"
	"unsafe"

	"bytes"
	"encoding/gob"

	jsoniter "github.com/json-iterator/go"
)

var json = jsoniter.ConfigCompatibleWithStandardLibrary

//@: 利用反射将结构体转化为map
func StructToMap(obj interface{}) map[string]interface{} {
	obj1 := reflect.TypeOf(obj)
	obj2 := reflect.ValueOf(obj)

	var data = make(map[string]interface{})
	for i := 0; i < obj1.NumField(); i++ {
		data[obj1.Field(i).Name] = obj2.Field(i).Interface()
	}
	return data
}

// 将数组格式化为字符串
func Array2String(array []interface{}) string {
	return strings.Replace(strings.Trim(fmt.Sprint(array), "[]"), " ", ",", -1)
}

// ValueInterfaceToString interface转string，非map[string]interface{}
func ValueInterfaceToString(value interface{}) string {
	var key string
	if value == nil {
		return key
	}

	switch value.(type) {
	case float64:
		ft := value.(float64)
		key = strconv.FormatFloat(ft, 'f', -1, 64)
	case float32:
		ft := value.(float32)
		key = strconv.FormatFloat(float64(ft), 'f', -1, 64)
	case int:
		it := value.(int)
		key = strconv.Itoa(it)
	case uint:
		it := value.(uint)
		key = strconv.Itoa(int(it))
	case int8:
		it := value.(int8)
		key = strconv.Itoa(int(it))
	case uint8:
		it := value.(uint8)
		key = strconv.Itoa(int(it))
	case int16:
		it := value.(int16)
		key = strconv.Itoa(int(it))
	case uint16:
		it := value.(uint16)
		key = strconv.Itoa(int(it))
	case int32:
		it := value.(int32)
		key = strconv.Itoa(int(it))
	case uint32:
		it := value.(uint32)
		key = strconv.Itoa(int(it))
	case int64:
		it := value.(int64)
		key = strconv.FormatInt(it, 10)
	case uint64:
		it := value.(uint64)
		key = strconv.FormatUint(it, 10)
	case string:
		key = value.(string)
	case []byte:
		key = string(value.([]byte))
	default:
		newValue, _ := json.Marshal(value)
		key = string(newValue)
	}

	return key
}

// MapInterfaceToString interface转string，针对map[string]interface{}的某个键
func MapInterfaceToString(_map map[string]interface{}, _key string) string {
	value := _map[_key].(string)
	return value
}

// ArrayInterfaceToString interface转string，准对一维数组[]string{}或[]int{}
func ArrayInterfaceToString(_array interface{}) string {
	value := fmt.Sprintf("%v", _array)
	return value
}

// str2Bool 将字符串转换为布尔值.
// 1, t, T, TRUE, true, True 等字符串为真;
// 0, f, F, FALSE, false, False 等字符串为假.
func StringToBool(val string) (res bool) {
	if val != "" {
		res, _ = strconv.ParseBool(val)
	}

	return
}

// StringToInt string转int
func StringToInt(_str string) int64 {
	_int, err := strconv.ParseInt(_str, 10, 64) // string转int
	if err != nil {                             // 报错则默认返回0
		_int = 0
		//fmt.Println("格式转换错误，默认为0。")
		//fmt.Println(err)
	}
	return _int
}

// IntToString int转string
func IntToString(val interface{}) string {
	switch val.(type) {
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		return fmt.Sprintf("%d", val)
	default:
		r := reflect.ValueOf(val)
		switch r.Kind() {
		case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
			return fmt.Sprintf("%d", r.Int())
		default:
			return ""
		}
	}

}

func ByteToString(_byte []byte) string {
	return string(_byte)
}

// runes2Bytes 将[]rune转为[]byte.
func RunesToBytes(rs []rune) []byte {
	size := 0
	for _, r := range rs {
		size += utf8.RuneLen(r)
	}

	bs := make([]byte, size)

	count := 0
	for _, r := range rs {
		count += utf8.EncodeRune(bs[count:], r)
	}

	return bs
}

func StringToByte(_str string) []byte {
	return []byte(_str)
}

// StringToRunes 字符串转为字符切片.
func StringToRunes(val string) []rune {
	return []rune(val)
}

func ByteToStringFast(_byte []byte) string {
	return *(*string)(unsafe.Pointer(&_byte))
}

func StringToByteFast(_str string) (_byte []byte) {
	ss := (*reflect.StringHeader)(unsafe.Pointer(&_str))
	bs := (*reflect.SliceHeader)(unsafe.Pointer(&_byte))
	bs.Data = ss.Data
	bs.Len = ss.Len
	bs.Cap = ss.Len
	return _byte
}

func Int32ToInt64(_int int32) int64 {
	return int64(_int)
}

func Int64ToInt32(_int int64) int32 {
	return int32(_int)
}

// StringToFloat string转float
func StringToFloat(_str string) float64 {
	_float, err := strconv.ParseFloat(_str, 64) // string转int
	if err != nil {                             // 报错则默认返回0
		_float = 0.0
		//fmt.Println("格式转换错误，默认为0。")
		//fmt.Println(err)
	}
	return _float
}

// FloatToString 将浮点数转换为字符串,decimal为小数位数.
func FloatToString(val interface{}, decimal int) string {
	if decimal <= 0 {
		decimal = 2
	}

	switch val.(type) {
	case float32:
		return strconv.FormatFloat(float64(val.(float32)), 'f', decimal, 32)
	case float64:
		return strconv.FormatFloat(val.(float64), 'f', decimal, 64)
	default:
		r := reflect.ValueOf(val)
		switch r.Kind() {
		case reflect.Float32:
			return strconv.FormatFloat(r.Float(), 'f', decimal, 32)
		case reflect.Float64:
			return strconv.FormatFloat(r.Float(), 'f', decimal, 64)
		default:
			return ""
		}
	}
}

func MapInterfaceToJson(_map map[string]interface{}) []byte {
	_json, _ := json.Marshal(_map)
	return _json
}

// toStr 强制将变量转换为字符串.
func ToString(val interface{}) string {
	//先处理其他类型
	v := reflect.ValueOf(val)
	switch v.Kind() {
	case reflect.Invalid:
		return ""
	case reflect.Bool:
		return strconv.FormatBool(v.Bool())
	case reflect.String:
		return v.String()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.FormatInt(v.Int(), 10)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return strconv.FormatUint(v.Uint(), 10)
	case reflect.Float32:
		return strconv.FormatFloat(v.Float(), 'f', -1, 32)
	case reflect.Float64:
		return strconv.FormatFloat(v.Float(), 'f', -1, 64)
	case reflect.Ptr, reflect.Struct, reflect.Map: //指针、结构体和字典
		b, err := json.Marshal(v.Interface())
		if err != nil {
			return ""
		}
		return string(b)
	}

	//再处理字节切片
	switch val.(type) {
	case []uint8:
		return string(val.([]uint8))
	}

	return fmt.Sprintf("%v", val)
}

func InterfaceToString(_array interface{}) string {
	key := ArrayInterfaceToString(_array)
	key = EncodeURL(key)
	return key
}

func JsonEncode(v interface{}) string {
	bytes, err := json.Marshal(v)
	if err != nil {
		return ""
	}
	return string(bytes)
}

// 需要判断返回值，否则会出问题
func JsonDecode(_string string, _type interface{}) error {
	return jsoniter.Unmarshal([]byte(_string), &_type)
}

// numeric2Float 将数值转换为float64.
func NumericToFloat(val interface{}) (res float64, err error) {
	switch val.(type) {
	case int:
		res = float64(val.(int))
	case int8:
		res = float64(val.(int8))
	case int16:
		res = float64(val.(int16))
	case int32:
		res = float64(val.(int32))
	case int64:
		res = float64(val.(int64))
	case uint:
		res = float64(val.(uint))
	case uint8:
		res = float64(val.(uint8))
	case uint16:
		res = float64(val.(uint16))
	case uint32:
		res = float64(val.(uint32))
	case uint64:
		res = float64(val.(uint64))
	case float32:
		res = float64(val.(float32))
	case float64:
		res = val.(float64)
	case string:
		str := val.(string)
		res, err = strconv.ParseFloat(str, 64)
	}
	return
}

// Dec2Bin 将十进制转换为二进制字符串.
func DecToBin(num int64) string {
	return strconv.FormatInt(num, 2)
}

// Bin2Dec 将二进制字符串转换为十进制.
func BinToDec(str string) (int64, error) {
	i, err := strconv.ParseInt(str, 2, 0)
	if err != nil {
		return 0, err
	}
	return i, nil
}

// SexToBin 将十六进制字符串转换为二进制字符串.
func HexToBin(str string) (string, error) {
	i, err := strconv.ParseInt(str, 16, 0)
	if err != nil {
		return "", err
	}
	return strconv.FormatInt(i, 2), nil
}

// BinToHex 将二进制字符串转换为十六进制字符串.
func BinToHex(str string) (string, error) {
	i, err := strconv.ParseInt(str, 2, 0)
	if err != nil {
		return "", err
	}
	return strconv.FormatInt(i, 16), nil
}

// DecToHex 将十进制转换为十六进制.
func DecToHex(num int64) string {
	return strconv.FormatInt(num, 16)
}

// HexToDec 将十六进制转换为十进制.
func HexToDec(str string) (int64, error) {
	start := 0
	if len(str) > 2 && str[0:2] == "0x" {
		start = 2
	}

	// bitSize 表示结果的位宽（包括符号位），0 表示最大位宽
	return strconv.ParseInt(str[start:], 16, 0)
}

// Hex2Byte 16进制字符串转字节切片.
func HexToByte(str string) ([]byte, error) {
	start := 0
	if len(str) > 2 && str[0:2] == "0x" {
		start = 2
	}

	h, e := hex.DecodeString(str[start:])
	return h, e
}

// Dec2Oct 将十进制转换为八进制.
func DecToOct(num int64) string {
	return strconv.FormatInt(num, 8)
}

// Oct2Dec 将八进制转换为十进制.
func OctToDec(str string) (int64, error) {
	start := 0
	if len(str) > 1 && str[0:1] == "0" {
		start = 1
	}

	return strconv.ParseInt(str[start:], 8, 0)
}

func BoolToInt(val bool) int {
	if val {
		return 1
	}
	return 0

}

// Ip2Long 将 IPV4 的字符串互联网协议转换成长整型数字.
func Ip2Long(ipAddress string) uint32 {
	ip := net.ParseIP(ipAddress)
	if ip == nil {
		return 0
	}
	return binary.BigEndian.Uint32(ip.To4())
}

// Long2Ip 将长整型转化为字符串形式带点的互联网标准格式地址(IPV4).
func Long2Ip(properAddress uint32) string {
	ipByte := make([]byte, 4)
	binary.BigEndian.PutUint32(ipByte, properAddress)
	ip := net.IP(ipByte)
	return ip.String()
}

// InterfaceToInt 强制将变量转换为整型.
// 数值类型将转为整型;
// 字符串将使用str2Int;
// 布尔型的true为1,false为0;
// 数组、切片、字典、通道类型将取它们的长度;
// 指针、结构体类型为1,其他为0.
func InterfaceToInt(val interface{}) (res int) {
	switch val.(type) {
	case int:
		res = val.(int)
	case int8:
		res = int(val.(int8))
	case int16:
		res = int(val.(int16))
	case int32:
		res = int(val.(int32))
	case int64:
		res = int(val.(int64))
	case uint:
		res = int(val.(uint))
	case uint8:
		res = int(val.(uint8))
	case uint16:
		res = int(val.(uint16))
	case uint32:
		res = int(val.(uint32))
	case uint64:
		res = int(val.(uint64))
	case float32:
		res = int(val.(float32))
	case float64:
		res = int(val.(float64))
	case string:
		res = int(StringToInt(val.(string)))
	case bool:
		res = BoolToInt(val.(bool))
	default:
		v := reflect.ValueOf(val)
		switch v.Kind() {
		case reflect.Array, reflect.Slice, reflect.Map, reflect.Chan:
			res = v.Len()
		case reflect.Ptr, reflect.Struct:
			res = 1
		}
	}

	return
}

// InterfaceToFloat 强制将变量转换为浮点型.
// 数值类型将转为浮点型;
// 字符串将使用str2Float64;
// 布尔型的true为1.0,false为0;
// 数组、切片、字典、通道类型将取它们的长度;
// 指针、结构体类型为1.0,其他为0.
func InterfaceToFloat(val interface{}) (res float64) {
	switch val.(type) {
	case int:
		res = float64(val.(int))
	case int8:
		res = float64(val.(int8))
	case int16:
		res = float64(val.(int16))
	case int32:
		res = float64(val.(int32))
	case int64:
		res = float64(val.(int64))
	case uint:
		res = float64(val.(uint))
	case uint8:
		res = float64(val.(uint8))
	case uint16:
		res = float64(val.(uint16))
	case uint32:
		res = float64(val.(uint32))
	case uint64:
		res = float64(val.(uint64))
	case float32:
		res = float64(val.(float32))
	case float64:
		res = val.(float64)
	case string:
		res = StringToFloat(val.(string))
	case bool:
		if val.(bool) {
			res = 1.0
		}
	default:
		v := reflect.ValueOf(val)
		switch v.Kind() {
		case reflect.Array, reflect.Slice, reflect.Map, reflect.Chan:
			res = float64(v.Len())
		case reflect.Ptr, reflect.Struct:
			res = 1.0
		}
	}

	return
}

// EncodeByte encode data to byte
func EncodeByte(data interface{}) ([]byte, error) {
	buffer := bytes.NewBuffer(nil)
	encoder := gob.NewEncoder(buffer)
	err := encoder.Encode(data)
	if err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}

// DecodeByte decode byte data to target object
func DecodeByte(data []byte, target interface{}) error {
	buffer := bytes.NewBuffer(data)
	decoder := gob.NewDecoder(buffer)
	return decoder.Decode(target)
}
